<?php

class TemplateController extends Controller {

    /**
     * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
     * using two-column layout. See 'protected/views/layouts/column2.php'.
     */
    public $layout = '//layouts/column2';

    /**
     * @var CActiveRecord the currently loaded data model instance.
     */
    private $_model;

    /**
     * @return array action filters
     */
    public function filters() {
        return array(
            'accessControl', // perform access control for CRUD operations
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules() {
        return array(
            array('allow', // allow all users to perform 'index' and 'view' actions
                'actions' => array('view', 'create', 'admin', 'delete'),
                'expression' => 'Yii::app()->user->getState("identity")->isAdmin() == true',
            ),
            array('deny', // deny all users
                'users' => array('*'),
            ),
        );
    }

    /**
     * Displays a particular model.
     */
    public function actionView() {
        $model = $this->loadModel();
        //$modelDC = Disciplina_Carga::model()->findAll('ID_TEMPLATE = '.$model->ID_TEMPLATE);
        $modelDC = new Disciplina_Carga();
        $modelDC->ID_TEMPLATE = $model->ID_TEMPLATE;
        $this->render('view', array(
            'model' => $model,
            'modelDC' => $modelDC,
        ));
    }

    /**
     * Creates a new model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     */
    public function actionCreate() {
        $model = new Template();
        $modelAU = new Ambiente_Uso();
        $modelAR = new Ambiente_Recurso();
        $arrayCS;
        $modelCS = array();
        $this->layout = '//layouts/column1';

        if (isset($_POST['Template'])) {

            /* PROCURA POR AMBIENTES DISPONÍVEIS */

            $arrayCS = $_POST['CargaSemestral'];
            //buscar ambientes que satisfazem os requisitos inseridos
            foreach ($arrayCS as $item) {
                $cs = new CargaSemestral();
                $cs->attributes = $item;
                $cs->findAmbientes();
                $modelCS = array_merge($modelCS, array($cs->getId() => $cs));
                if (count($cs->ambientes) <= 0) {
                    MethodUtils::setMsgErro(FALSE, 'Nenhum ambiente atende os requisitos da disciplina ' . $cs->getId(), get_class($model));
                    $model->attributes = $_POST['Template'];
                    $this->render('passo1', array(
                        'model' => $model,
                        'modelAU' => $modelAU,
                        'modelAR' => $modelAR,
                        'modelCS' => $modelCS,
                    ));
                    return;
                }
                
            }
            uasort($modelCS, array("TemplateController", "compareDisciplinas"));

            if (isset($_POST['yt0'])) {
                if ($_POST['yt0'] == 'Voltar') {
                    $model->attributes = $_POST['Template'];
                    $this->render('passo1', array(
                        'model' => $model,
                        'modelAU' => $modelAU,
                        'modelAR' => $modelAR,
                        'modelCS' => $modelCS,
                    ));
                    return;
                }
            } else if (isset($_POST['yt1'])) {
                if ($_POST['yt1'] == 'Finalizar') {
                    $transaction = Yii::app()->db->beginTransaction();
                    try {

                        $model->attributes = $_POST['Template'];
                        $a = $model->DT_INI . '/' . $model->NU_ANO;
                        $model->DT_INI = MethodUtils::getDateInTableFormat($model->DT_INI . '/' . $model->NU_ANO);
                        $model->DT_FIM = MethodUtils::getDateInTableFormat($model->DT_FIM . '/' . $model->NU_ANO);
                        $isValid = $model->save();

                        /* SALVAR DISCIPLINA_CARGA NO BANCO */

                        if ($isValid) {
                            $this->SalvarDisciplinaCargas($model, $modelCS);
                        }

                        /* ALOCAR DISCIPLINA_CARGA'S SALVAS */

                        $this->AlocarDisciplinaCargas($model, $modelCS);

                        $transaction->commit();
                        MethodUtils::setMsgErro(TRUE, 'Carga Realizada com sucesso.', get_class($model));
                    } catch (Exception $e) {
                        $transaction->rollBack();
                    }
                }
            }

            /* ALGORITMO DE ESCOLHA DO AMBIENTE DA DISCIPLINA */

            //começar com as disciplinas com menos ambientes possíveis
            $algoritmo = new AlgoritmoAlocacao($modelCS);
            $sucesso = $algoritmo->init();

            $model->attributes = $_POST['Template'];
            if ($sucesso && $model->validate()) {
                $this->render('passo2', array(
                    'model' => $model,
                    'modelAU' => $modelAU,
                    'modelAR' => $modelAR,
                    'modelCS' => $modelCS,
                ));
            } else {
                //TODO: avisar porque falhou
                $this->render('passo1', array(
                    'model' => $model,
                    'modelAU' => $modelAU,
                    'modelAR' => $modelAR,
                    'modelCS' => $modelCS,
                ));
            }
        } else {
            if (isset($_GET['id'])) {
                $model = $model->findByPk($_GET['id']);
                $arrayDC = Disciplina_Carga::model()->findAllByAttributes(array('ID_TEMPLATE' => $model->ID_TEMPLATE));
                $uso = Uso::model()->findAll();
                foreach ($arrayDC as $dc) {
                    $cs = new CargaSemestral();
                    $cs->disciplina = $dc->ID_DISCIPLINA;
                    $cs->turma = $dc->TX_TURMA;
                    $cs->diasSemana = $dc->TX_DIAS;
                    $cs->horaIni = $dc->HR_INI;
                    $cs->horaFim = $dc->HR_FIM;
                    $cs->ambienteSelecionado = Ambiente::model()->findByPk($dc->ID_AMBIENTE);
                    $cs->capacidade = $dc->NU_CAPACIDADE;
                    $cs->finalidade = $dc->ID_FINALIDADE;
                    $cs->finalidadeText = $uso[$cs->finalidade]['TX_DESCRICAO'];
                    $cs->professor = $dc->TX_PROFESSOR;
                    $modelCS = array_merge($modelCS, array($cs->getId() => $cs));
                }
                uasort($modelCS, array("TemplateController", "compareDisciplinas"));
            }
            $this->render('passo1', array(
                'model' => $model,
                'modelAU' => $modelAU,
                'modelAR' => $modelAR,
                'modelCS' => $modelCS,
            ));
        }
    }

    private function SalvarDisciplinaCargas(Template $model, $modelCS) {
        $isValid = true;
        foreach ($modelCS as $cs) {
            $modelD = new Disciplina_Carga();
            $modelD->setAttributesMOD($cs, $model->ID_TEMPLATE);
            $isValid &= $modelD->save();
            if (!$isValid) {
                MethodUtils::setMsgErro(FALSE, 'Não foi possível salvar disciplina.', get_class($model));
                throw new Exception;
            }
        }
    }

    private function AlocarDisciplinaCargas(Template $model, $modelCS) {
        //obter data inicial da carga
        $bla = $model->DT_INI;
        $ble = $model->DT_FIM;
        $dtIniCarga = DateTime::createFromFormat('Y-m-d', $model->DT_INI);
        $dtFimCarga = DateTime::createFromFormat('Y-m-d', $model->DT_FIM);
        foreach ($modelCS as $cs) {
            $ini = $dtIniCarga;
            $dias = MethodUtils::getArrayDias($cs->diasSemana);
            while ($ini <= $dtFimCarga) {
                $a = date('w', $ini->getTimestamp());
                if ($dias[$a] == '1') {

                    /* VERIFICAR COLISÃO */

                    $this->VerificaColisao($model, $ini, $cs);

                    /* SALVAR ALOCACAO NO BANCO */

                    $modelAlocacao = new Alocacao();
                    $modelAlocacao->DT_DIA = date('d/m/Y', $ini->getTimestamp());
                    $modelAlocacao->HR_INI = $cs->horaIni;
                    $modelAlocacao->HR_FIM = $cs->horaFim;
                    $modelAlocacao->ID_AMBIENTE = $cs->ambienteSelecionado->ID_AMBIENTE;
                    $modelAlocacao->ID_TEMPLATE = $model->ID_TEMPLATE;
                    $modelAlocacao->ID_USO = $cs->finalidade;
                    $modelAlocacao->ID_USUARIO = Yii::app()->user->getState("identity")->getId();
                    $modelAlocacao->TX_DESCRICAO = $cs->disciplina;
                    $modelAlocacao->TX_INTERESSADO = $cs->professor;
                    if (!$modelAlocacao->save()) {
                        MethodUtils::setMsgErro(FALSE, 'Não foi possível alocar a disciplina ' . $cs->ID_DISCIPLINA . ' no dia ' . $modelAlocacao->DT_DIA, get_class($model));
                        throw new Exception;
                    }
                }
                $ini->modify('+1 day');
            }
        }
    }

    function VerificaColisao(Template $model, DateTime $ini, CargaSemestral $cs) {
        $alocateds = Alocacao::model()->findAllByAttributes(array(
            'DT_DIA' => date('Y-m-d', $ini->getTimestamp()),
            'ID_AMBIENTE' => $cs->ambienteSelecionado->ID_AMBIENTE
                ));
        if (is_array($alocateds)) {
            foreach ($alocateds as $alocated) {
                if (($alocated->HR_INI >= $cs->horaIni && $alocated->HR_INI <= $cs->horaFim) || ($alocated->HR_FIM >= $cs->horaIni && $alocated->HR_FIM <= $cs->horaFim)) {
                    //TODO: tratar colisão
                    $mensagem = 'Colisão encontrada - ' . $alocated->DT_DIA . ' ' . $cs->getId() . ' - ' . MethodUtils::getTimeFromInt($alocated->HR_INI) . ' as ' . MethodUtils::getTimeFromInt($alocated->HR_FIM);
                    MethodUtils::setMsgErro(FALSE, $mensagem, get_class($model));
                    throw new Exception('colisão');
                }
            }
        }
    }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     */
    public function actionUpdate() {
        $model = $this->loadModel();

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if (isset($_POST['Template'])) {
            $model->attributes = $_POST['Template'];
            if ($model->save())
                $this->redirect(array('view', 'id' => $model->ID_TEMPLATE));
        }

        $this->render('update', array(
            'model' => $model,
        ));
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     */
    public function actionDelete() {
        if (Yii::app()->request->isPostRequest) {
            // we only allow deletion via POST request
            $this->loadModel()->delete();

            // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
            if (!isset($_GET['ajax']))
                $this->redirect(array('admin'));
        }
        else
            throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
    }

    /**
     * Lists all models.
     */
    public function actionIndex() {
        $dataProvider = new CActiveDataProvider('Template');
        $this->render('index', array(
            'dataProvider' => $dataProvider,
        ));
    }

    /**
     * Manages all models.
     */
    public function actionAdmin() {
        $model = new Template('search');
        $model->unsetAttributes();  // clear any default values
        if (isset($_GET['Template']))
            $model->attributes = $_GET['Template'];

        $this->render('admin', array(
            'model' => $model,
        ));
    }

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     */
    public function loadModel() {
        if ($this->_model === null) {
            if (isset($_GET['id']))
                $this->_model = Template::model()->findbyPk($_GET['id']);
            if ($this->_model === null)
                throw new CHttpException(404, 'The requested page does not exist.');
        }
        return $this->_model;
    }

    /**
     * Performs the AJAX validation.
     * @param CModel the model to be validated
     */
    protected function performAjaxValidation($model) {
        if (isset($_POST['ajax']) && $_POST['ajax'] === 'template-form') {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }

    static function compareDisciplinas($a, $b) {
        $na = count($a->ambientes);
        $nb = count($b->ambientes);
        if ($na == $nb) {
            return 0;
        }
        return ($na < $nb) ? -1 : 1;
    }

}
